package drds.common.db.sql_mapping.dynamic_tag.sql_template;


import drds.common.db.sql_mapping.configuration.Configuration;
import drds.common.db.sql_mapping.dynamic_tag.tag.CompositeTag;
import drds.common.db.sql_mapping.dynamic_tag.tag.Tag;
import drds.common.db.sql_mapping.dynamic_tag.tag.TextTag;
import drds.common.db.sql_mapping.dynamic_tag.tag.VariableReplacementTextTag;
import drds.common.db.sql_mapping.dynamic_tag.tag_handler.*;
import drds.common.db.sql_mapping.dynamic_tag.xml_node.XmlNode;
import org.w3c.dom.NodeList;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * mapper桥接tag
 */
public class XmlMapperBuilder {
    public final Map<String, TagHandler> tagNameToXmlNodeHandlerMap = new HashMap<>();
    public Configuration configuration;
    public final XmlNode mapperXmlNode;
    public boolean isDynamic;


    public XmlMapperBuilder(Configuration configuration, XmlNode mapperXmlNode) {
        this.configuration = configuration;
        this.mapperXmlNode = mapperXmlNode;
        initTagToXmlNodeHandlerMap();
    }


    private void initTagToXmlNodeHandlerMap() {
        tagNameToXmlNodeHandlerMap.put("bind", new BindTagHandler());
        tagNameToXmlNodeHandlerMap.put("foreach", new ForEachTagHandler(this));
        //
        tagNameToXmlNodeHandlerMap.put("if", new IfTagHandler(this));
        //
        tagNameToXmlNodeHandlerMap.put("choose", new ChooseTagHandler(this));
        tagNameToXmlNodeHandlerMap.put("when", new IfTagHandler(this));
        tagNameToXmlNodeHandlerMap.put("otherwise", new OtherwiseTagHandler(this));
        //
    }

    public SqlTemplate parseMapperXmlNode() {
        CompositeTag rootNode = parseTags(mapperXmlNode);
        SqlTemplate sqlTemplate;
        /**
         * 不同格式的sql模版在sql具体调用的时候遍历节点树动态生成sql
         */
        if (isDynamic) {
            sqlTemplate = new DynamicSqlTemplate(configuration, rootNode);
        } else {
            sqlTemplate = new RawSqlTemplate(configuration, rootNode);
        }
        return sqlTemplate;
    }

    /**
     * tagList的执行顺序是同级从左到右,父子从上到下。
     */
    public CompositeTag parseTags(XmlNode xmlNode) {
        List<Tag> tagList = new ArrayList<>();
        NodeList childrenNodeList = xmlNode.getNode().getChildNodes();
        for (int i = 0; i < childrenNodeList.getLength(); i++) {
            XmlNode childXmlNode = xmlNode.newXmlNode(childrenNodeList.item(i));
            if (childXmlNode.getNode().getNodeType() == org.w3c.dom.Node.CDATA_SECTION_NODE || childXmlNode.getNode().getNodeType() == org.w3c.dom.Node.TEXT_NODE) {
                String body = childXmlNode.getStringBody("");
                VariableReplacementTextTag variableReplacementTextTag = new VariableReplacementTextTag(body);
                if (variableReplacementTextTag.isHasToken()) {
                    tagList.add(variableReplacementTextTag);
                    isDynamic = true;
                } else {
                    tagList.add(new TextTag(body));
                }
            } else if (childXmlNode.getNode().getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) {
                String tagName = childXmlNode.getNode().getNodeName();
                TagHandler tagHandler = tagNameToXmlNodeHandlerMap.get(tagName);
                if (tagHandler == null) {
                    throw new RuntimeException("Unknown element <" + tagName + "> in SQL statement_handler.");
                }
                tagHandler.handleNode(childXmlNode, tagList);
                isDynamic = true;
            }
        }
        return new CompositeTag(tagList);
    }

}
